import sys
import os
from collections import deque
from datetime import datetime

import torch
import torch.nn as nn
import torch.optim as optim
# import torch.nn.functional as F
import random
import math
import numpy as np

import pandas as pd
import json

import matplotlib.pyplot as plt

#from model.model_test import TestingInfo, TestingInfoCdu, TestingInfoFsu
from util.loguru_util import myLogger
from torch.optim.lr_scheduler import StepLR
from util.model_class import Model
from all_config import state_dict_path, is_not_restart_new_model, model


import pickle

from util.mysql_connnect import get_db, get_engine, SessionLocal

# result_data = [
#     '{"dryValve": "0,0,0,0,0", "pumpFrontPress": "94", "equipment_id": null, "dryOutPress": "444,452,452,449,439", "dryFan": "0,0,0,0,0", "pumpOutletTemp": "151", "temperature": "23273,-8879", "pumpOutPress": "196", "humidity": "2053,2050", "pumpFillWaterFilterFrtPress": "16", "dryInPress": "273,275,283,277,293", "pumpInTemp": "148", "pumpFillWaterFilterRearPress": "3", "dryFlow": "2954,2167,2844,2142,2936", "pumpInPress": "109", "pumpFlow": "458", "id": "bd6caa015a77d82a3a6489dbbeadaeee", "dryOutTemp": "-95,-92,-93,-95,-91", "pumpFilterFrontPress": "106", "pumpPump": "57", "testing_time": "2024-03-27 15:04:07", "dryInTemp": "-97,-93,-875,-96,-88", "pumpFilterRearPress": "96", "pumpBypassValve": "2"}',
#     '{"equipment_id": null, "testing_time": "2024-03-27 15:04:07", "cduPfi": "112", "cduPfo": "109", "cduTsi": "190", "cduPsi": "149", "cduPso": "264", "cduValve1": "10", "cduPump2": "0", "cduValve2": "100", "id": "81999f646d8eee9e46e5c36c63b413c6", "cduTfi": "161", "cduTfo": "184", "cduFf": "0", "cduTso": "197", "cduFs": "2450", "cduPump1": "51", "cduValve2by": "0"}',
#     '{"pduEnergy": null, "dryCooler4Energy": null, "cabinet1Energy": null, "cabinet1Flow": null, "sensorTh2Humi": null, "dryCooler1Power": null, "dryCooler5Power": null, "cabinet2Power": null, "cabinet2Ti": null, "dryCooler1Energy": null, "dryCooler5Energy": null, "cabinet2Energy": null, "cabinet2Pi": null, "dryCooler2Power": null, "pumpCabinetPower": null, "cabinet1Ti": null, "cabinet2To": null, "equipment_id": null, "dryCooler2Energy": null, "pumpCabinetEnergy": null, "cabinet1Pi": null, "cabinet2Po": null, "id": "0997f661a7b75a4ffa52d3af1456ed7a", "dryCooler3Power": null, "cduPower": null, "cabinet2Flow": null, "sensorTh1Temp": null, "testing_time": "2024-03-27 15:04:07", "dryCooler3Energy": null, "cduEnergy": null, "cabinet1To": null, "sensorTh1Humi": null, "pduPower": null, "dryCooler4Power": null, "cabinet1Power": null, "cabinet1Po": null, "sensorTh2Temp": null}']

curr_time = datetime.now().strftime("%Y%m%d-%H%M%S")  # 获取当前时间
curr_path = os.path.dirname(os.path.abspath(__file__))  # 当前文件所在绝对路径
parent_path = os.path.dirname(curr_path)  # 父路径
sys.path.append(parent_path)  # 添加路径到系统路径


debug = False


# class Config:
#     def __init__(self):
#         #######################  Environmental Parameters   ###########################
#         self.algo_name = 'DQN'  # 算法名称
#         self.env_name = 'Cooling System'  # 环境名称
#         #self.device = torch.device("cpu")  # 检测GPUgjgjlkhfsf风刀霜的撒发十
#         self.device = torch.device(
#             "cuda" if torch.cuda.is_available() else "cpu")  # 检测GPUgjgjlkhfsf风刀霜的撒发十
#
#         # self.device = torch.device("cpu")  # 检测GPUgjgjlkhfsf风刀霜的撒发十
#         # self.seed = 10 # 随机种子，置0则不设置随机种子
#         # 训练轮数
#
#         if debug == True:
#             self.train_eps = 100  # 训练的回合数
#         else:
#             self.train_eps = 20000  # 训练的回合数
#
#         self.test_eps = 5  # 测试的回合数
#         #############################################################################
#
#         ############################# Hyperparameters ################################
#         self.gamma = 0.9  # 强化学习中的折扣因子
#         self.epsilon_start = 0.15  # e-greedy策略中初始epsilon
#         self.epsilon_end = 0.1 # e-greedy策略中的终止epsilon
#         # todo 如果跑的效果不行 改成0.9到0.15
#         self.epsilon_decay = 300  # e-greedy策略中epsilon的衰减率
#         self.learn_rate = 0.001  # 学习率
#         if __name__ == '__main__':
#             self.memory_capacity = 20000  # 离线训练的时候，将经验池容量设置为20000
#         else:
#             self.memory_capacity = 6400 # 否则设置成6400
#         #myLogger.info(f"经验池大小为：{self.memory_capacity}")
#         # batch_size 大小
#         if debug == True:
#             self.batch_size = 2  # mini-batch SGD中的批量大小
#         else:
#             self.batch_size = 8  # mini-batch SGD中的批量大小
#         self.target_update = 4  # 目标网络的更新频率
#         self.target_update_count = 0  # 目标网络的計數
#         self.model_save_steps = 128
#         self.tau = 0.9
#         # self.hidden_dim = 256  # 网络隐藏层
#         ################################################################################
#
#         ############################### State-Action Space  ############################
#         # 需要重新定义state_dim 和 action_space
#         # self.state_dim = 70
#         # self.action_space = [(dryValve_A, dryFan_A, pumpPump_A,pumpBypassValve_A, cduValve1_A, cduPump1_A, cduPump2_A, cduValve2by_A,cduValve2_A )
#         #                      for dryValve_A in [0,  100]
#         #                      for dryFan_A in [0,  100]
#         #                      for pumpPump_A in [0, 100]
#         #                      for pumpBypassValve_A in [0,  100]
#         #                      for cduValve1_A in [0, 100]
#         #                      for cduPump1_A in [0,  100]
#         #                      for cduPump2_A in [0,  100]
#         #                      for cduValve2by_A in [0,  100]
#         #                      for cduValve2_A in [0,  100]
#         #                      ]
#         # self.action_dim = len(self.action_space)
#         self.all_state_dim = 3
#         #self.longrun_state_dim = 46
#         self.all_action_space = [(dryFan, pumpPump,cduValve1)
#                                      # for dryValve in [0, 100]
#                                      for dryFan in list(range(5,  95, 5))
#                                      for pumpPump in list(range(30, 80, 2))
#                                      for cduValve1 in list(range(10, 90, 5))
#                                      ]
#         self.all_action_space_dim = len(self.all_action_space)
#         # self.dryfan_action_space = [(dryFan)
#         #                              # for dryValve in [0, 100]
#         #                              for dryFan in list(range(0, 101, 1))
#         #                              ]
#         # self.dryfan_action_dim = len(self.dryfan_action_space)
#         # pumpPump希望控制的更细致些
#         #
#         # cduPump没有用了
#
#
#         #self.cdu_state_dim = 17
#         # self.pump_action_space = [(pumpPump)
#         #                          for pumpPump in list(range(30, 81))
#         #                         ]
#         # self.pump_action_dim = len(self.pump_action_space)
#
#         # 融合在一起进行定义
#
#         # self.cdu_action_space = [(cduValve1)
#         #                          for cduValve1 in list(range(0, 91, 1))
#         #                          ]
#         # self.cdu_action_dim = len(self.cdu_action_space)
#
#         # self.cdu_action_space = [(cduValve1, cduPump1, cduPump2, cduValve2by,cduValve2)
#         #                              for cduValve1 in [0, 20, 40, 60, 80, 100]
#         #                              for cduPump1 in [0, 20, 40, 60, 80, 100]
#         #                              for cduPump2 in [0, 20, 40, 60, 80, 100]
#         #                              for cduValve2by in [0, 20, 40, 60, 80, 100]
#         #                              for cduValve2 in [0, 20, 40, 60, 80, 100]
#         #                              ]
#         # self.cdu_action_space = [(cduValve1,cduPump1) for cduValve1 in range(101) for cduPump1 in [0, 20, 40, 60, 80, 100]]
#         # 8月26日
#         # self.cdu_action_space = [(cduValve1, cduPump1, cduPump2, cduValve2by,cduValve2)
#         #                          for cduValve1 in [10,20,30,40,50,60,70,80,90,100]
#         #                          for cduPump1 in [20, 40, 60, 80, 100]
#         #                          for cduPump2 in [0]
#         #                          for cduValve2by in [0]
#         #                          for cduValve2 in [100]
#         #                          ]
#         # self.cdu_action_dim = len(self.cdu_action_space)
#
#         # cdu的动作空间，在0331的版本基础上将其，动作值改为[10,20,30,40,50,60,70,80,90,100]
#         # self.cdu_action_space = [(cduValve1, cduPump1)
#         #                        for cduValve1 in [10,20,30,40,50,60,70,80,90,100]
#         #                         for cduPump1 in [20, 40, 60, 80 ,100]
#         #                         ]
#
#         # self.cdu_action_space = [cduValve1 for cduValve1 in range(16 ,101, 1) ]
#         # self.cdu_action_dim = len(self.cdu_action_space)
#
#         ################################################################################
#
#         ################################# Cooling System ################################
#         self.water_temp_standard = 40
#         self.water_temp_wave_threshold = 0.0125
#         self.pue_standard = 1.33
#         ############################################################################
#
#         ################################# Save Results ################################
#         self.result_path = curr_path + "/outputs/" + self.env_name + \
#                            '/' + curr_time + '/results/'  # 保存结果的路径
#         self.model_path = curr_path + "/outputs/" + self.env_name + \
#                           '/' + curr_time + '/models/'  # 保存模型的路径
#         self.save = False  # 是否保存图片
#         ################################################################################


# class Neural_Network(nn.Module):
#     def __init__(self, state_dim, action_dim):
#         super(Neural_Network, self).__init__()
#         self.dense1 = nn.Linear(state_dim, 512)
#         self.dense2 = nn.Linear(512, action_dim)
#         #self.dense3 = nn.Linear(512, action_dim)
#         # self.dense4 = nn.Linear(2048, 8192)
#         self.output_layer = nn.Linear(action_dim, action_dim)
#
#     def forward(self, state):
#         x = torch.relu(self.dense1(state))
#         x = torch.relu(self.dense2(x))
#         # x = torch.relu(self.dense4(x))
#         # print(len(self.output_layer(x)))
#         return self.output_layer(x)


#
# class Model(torch.nn.Module):
#     def __init__(self):
#         super(Model, self).__init__()
#         self.linear1 = torch.nn.Linear(6, 6)
#         self.linear2 = torch.nn.Linear(6, 4)
#         self.linear3 = torch.nn.Linear(4, 1)
#     def forward(self, x):
#         x= torch.relu(self.linear1(x))
#         x= torch.relu(self.linear2(x))
#         x = self.linear3(x)
#         return x

# 定义模型


class FIFO_Stack:
    def __init__(self):
        self.stack = deque(maxlen=2)  # 使用deque，并设置最大长度为3

    def data_to_stack(self, data):
        self.stack.append(data)

    def stack_display(self):
        myLogger.info(list(self.stack)[0])
        myLogger.info(list(self.stack)[-1])

    def transaction_data(self):
        self.data_0 = list(self.stack)[0]
        self.data_1 = list(self.stack)[-1]
        return self.data_0, self.data_1


class Replay_Buffer:
    def __init__(self, capacity):
        self.capacity = capacity  # 经验回放的容量
        self.buffer = []  # 缓冲区
        self.position = 0

    def push(self, state_now, label_now):
        '''
        缓冲区是一个队列，容量超出时去掉开始存入的转移(transition)
        这个地方的队列规则是通过position来进行控制的，当position到达capcacity的一个周期时，
        则重置，所以不会超过capacity
        '''
        if len(self.buffer) < self.capacity:
            self.buffer.append(None)
        # self.buffer[self.position] = (state, action, reward, next_state)
        self.buffer[self.position] = (state_now, label_now)
        self.position = (self.position + 1) % self.capacity

    def sample(self, batch_size):
        mini_batch = random.sample(self.buffer, batch_size)  # 随机采出小批量转移
        state_now, label_now  = zip(*mini_batch)  # 解压成状态，动作等
        return list(state_now), list(label_now)

    def __len__(self):
        ''' 返回当前存储的量
        '''
        return len(self.buffer)





def process_longrundata_neural(input_dict_1):
    input_dict = input_dict_1.copy()
    # 删除不需要的数据
    keys_to_remove = ['id', 'equipment_id']
    for key in keys_to_remove:
        input_dict.pop(key, None)

    # 'testing_time' 中仅取月份值
    testing_time = input_dict.get('testing_time', None)
    if testing_time:
        month = testing_time.split('-')[1]
        try:
            hour = testing_time.split(' ')[1].split(':')[0]
        except:
            hour = testing_time.split('T')[1].split(':')[0]
        else:
            hour = testing_time.split(' ')[1].split(':')[0]
        input_dict['testing_time'] = int(month)
        input_dict['testing_time_hour'] = int(hour)

    # 按照excel表格中的参数顺序排序
    order_keys = [
        'testing_time', 'testing_time_hour','dryFan1','dryFan2','dryFan3','dryFan4','dryFan5','temperature',
        'pumpOutPress',  'pumpPump']

    sorted_dict = {key: input_dict[key] for key in order_keys if key in input_dict}

    # for key, value in sorted_dict.items():
    #     if ',' in value:  # 检测是否存在多个值
    #         values_list = [val for val in value.split(',')]
    #         sorted_dict[key] = random.choice(values_list)  # 随机选一个值作为状态值
    #     else:
    #         sorted_dict[key] = value

    for key, value in sorted_dict.items():
        # 确保值是字符串类型，然后再检查是否包含逗号
        if isinstance(value, str) and ',' in value:
            values_list = [val for val in value.split(',')]
            sorted_dict[key] = random.choice(values_list)  # 随机选一个值作为状态值

    for key, value in sorted_dict.items():
        # sorted_dict[key] = int(value)  # 转换成int类型值
        sorted_dict[key] = float(value)  # 转换成float类型值

    return sorted_dict

# def process_cdudata(input_dict_1):
#     input_dict = input_dict_1.copy()
#     # 删除不需要的数据
#     keys_to_remove = ['id', 'equipment_id']
#     for key in keys_to_remove:
#         input_dict.pop(key, None)
#
#     # 'testing_time' 中仅取月份值
#     testing_time = input_dict.get('testing_time', None)
#     if testing_time:
#         month = testing_time.split('-')[1]
#         try:
#             hour = testing_time.split(' ')[1].split(':')[0]
#         except:
#             hour = testing_time.split('T')[1].split(':')[0]
#         else:
#             hour = testing_time.split(' ')[1].split(':')[0]
#         input_dict['testing_time'] = month
#         input_dict['testing_time_hour'] = hour
#
#     #按照excel表格中的参数顺序排序
#     order_keys = [
#         'testing_time', 'testing_time_hour','cduTfi', 'cduPfi', 'cduTfo', 'cduPfo', 'cduFf', 'cduTsi', 'cduPsi',
#         'cduTso', 'cduPso', 'cduFs', 'cduValve1', 'cduPump1', 'cduPump2', 'cduValve2by', 'cduValve2'
#     ]
#
#
#     sorted_dict = {key: input_dict[key] for key in order_keys if key in input_dict}
#
#     for key, value in sorted_dict.items():
#         # sorted_dict[key] = int(value)  # 转换成int类型值
#         sorted_dict[key] = float(value)  # 转换成float类型值
#
#     return sorted_dict

def process_cdudata_neural(input_dict_1):
    input_dict = input_dict_1.copy()
    # 删除不需要的数据
    input_dict = input_dict_1.copy()
    keys_to_remove = ['id', 'equipment_id']
    for key in keys_to_remove:
        input_dict.pop(key, None)


    # 按照excel表格中的参数顺序排序
    order_keys = [
        'cduTfi', 'cduPfi', 'cduTfo', 'cduPfo', 'cduFf', 'cduTsi', 'cduPsi',
        'cduTso', 'cduPso', 'cduFs', 'cduValve1', 'cduPump1', 'cduPump2', 'cduValve2by', 'cduValve2'
    ]

    #order_keys = [
    #        'cduTfi', 'cduTfo','cduTsi', 'cduTso','cduValve1']
    sorted_dict = {key: input_dict[key] for key in order_keys if key in input_dict}

    for key, value in sorted_dict.items():
        # sorted_dict[key] = int(value)  # 转换成int类型值
        sorted_dict[key] = float(value)  # 转换成float类型值

    return sorted_dict

def process_fsudata_neural(input_dict_1):
    input_dict = input_dict_1.copy()
    # for key, value in input_dict.items():
    #     if not value:  # 判断value是否为空
    #         myLogger.error(f"Error: The value of FSU data for key '{key}' is empty.")
    #         input_dict[key] = "65535"

    # 删除不需要的数据
    keys_to_remove = ['id', 'equipment_id', 'testing_time']
    for key in keys_to_remove:
        input_dict.pop(key, None)

    # 'testing_time' 中仅取月份值
    # testing_time = input_dict.get('testing_time', None)
    # if testing_time:
    #     month = testing_time.split('-')[1]
    #     input_dict['testing_time'] = month

    # 按照excel表格中的参数顺序排序
    # order_keys = [
    #     'pduPower', c, 'dryCooler1Power', 'dryCooler1Energy', 'dryCooler2Power', 'dryCooler2Energy',
    #     'dryCooler3Power', 'dryCooler3Energy', 'dryCooler4Power',
    #     'dryCooler4Energy', 'dryCooler5Power', 'dryCooler5Energy', 'pumpCabinetPower', 'pumpCabinetEnergy', 'cduPower',
    #     'cduEnergy', 'cabinet1Power', 'cabinet1Energy', 'cabinet2Power', 'cabinet2Energy',
    #     'cabinet1Ti', 'cabinet1Pi', 'cabinet1To', 'cabinet1Po', 'cabinet1Flow', 'cabinet2Ti', 'cabinet2Pi',
    #     'cabinet2To', 'cabinet2Po', 'cabinet2Flow',
    #     'sensorTh1Temp', 'sensorTh1Humi', 'sensorTh2Temp', 'sensorTh2Humi',
    #     'heater1Voltage1', 'heater1Current1', 'heater1Power1', 'heater1TempIn1', 'heater1TempOut1', 'heater1PressIn1',
    #     'heater1PressOut1', 'heater1Voltage2', 'heater1Current2', 'heater1Power2', 'heater1TempIn2', 'heater1TempOut2',
    #     'heater1PressIn2', 'heater1PressOut2', 'heater2Voltage1', 'heater2Current1', 'heater2Power1', 'heater2TempIn1',
    #     'heater2TempOut1', 'heater2PressIn1', 'heater2PressOut1', 'heater2Voltage2', 'heater2Current2', 'heater2Power2',
    #     'heater2TempIn2', 'heater2TempOut2', 'heater2PressIn2', 'heater2PressOut2', 'heater3Voltage1',
    #     'heater3Current1',
    #     'heater3Power1', 'heater3TempIn1', 'heater3TempOut1', 'heater3PressIn1', 'heater3PressOut1', 'heater3Voltage2',
    #     'heater3Current2', 'heater3Power2', 'heater3TempIn2', 'heater3TempOut2', 'heater3PressIn2', 'heater3PressOut2',
    #     'heater4Voltage1', 'heater4Current1', 'heater4Power1', 'heater4TempIn1', 'heater4TempOut1', 'heater4PressIn1',
    #     'heater4PressOut1', 'heater4Voltage2', 'heater4Current2', 'heater4Power2', 'heater4TempIn2', 'heater4TempOut2',
    #     'heater4PressIn2', 'heater4PressOut2', 'heater5Voltage1', 'heater5Current1', 'heater5Power1', 'heater5TempIn1',
    #     'heater5TempOut1', 'heater5PressIn1', 'heater5PressOut1', 'heater5Voltage2', 'heater5Current2', 'heater5Power2',
    #     'heater5TempIn2', 'heater5TempOut2', 'heater5PressIn2', 'heater5PressOut2', 'heater6Voltage1',
    #     'heater6Current1',
    #     'heater6Power1', 'heater6TempIn1', 'heater6TempOut1', 'heater6PressIn1', 'heater6PressOut1', 'heater6Voltage2',
    #     'heater6Current2', 'heater6Power2', 'heater6TempIn2', 'heater6TempOut2', 'heater6PressIn2', 'heater6PressOut2',
    #     'heater7Voltage1', 'heater7Current1', 'heater7Power1', 'heater7TempIn1', 'heater7TempOut1', 'heater7PressIn1',
    #     'heater7PressOut1', 'heater7Voltage2', 'heater7Current2', 'heater7Power2', 'heater7TempIn2', 'heater7TempOut2',
    #     'heater7PressIn2', 'heater7PressOut2', 'heater8Voltage1', 'heater8Current1', 'heater8Power1', 'heater8TempIn1',
    #     'heater8TempOut1', 'heater8PressIn1', 'heater8PressOut1', 'heater8Voltage2', 'heater8Current2', 'heater8Power2',
    #     'heater8TempIn2', 'heater8TempOut2', 'heater8PressIn2', 'heater8PressOut2', 'heater9Voltage1',
    #     'heater9Current1',
    #     'heater9Power1', 'heater9TempIn1', 'heater9TempOut1', 'heater9PressIn1', 'heater9PressOut1', 'heater9Voltage2',
    #     'heater9Current2', 'heater9Power2', 'heater9TempIn2', 'heater9TempOut2', 'heater9PressIn2', 'heater9PressOut2',
    #     'heater10Voltage1', 'heater10Current1', 'heater10Power1', 'heater10TempIn1', 'heater10TempOut1',
    #     'heater10PressIn1',
    #     'heater10PressOut1', 'heater10Voltage2', 'heater10Current2', 'heater10Power2', 'heater10TempIn2',
    #     'heater10TempOut2',
    #     'heater10PressIn2', 'heater10PressOut2', 'heater11Voltage1', 'heater11Current1', 'heater11Power1',
    #     'heater11TempIn1',
    #     'heater11TempOut1', 'heater11PressIn1', 'heater11PressOut1', 'heater11Voltage2', 'heater11Current2',
    #     'heater11Power2',
    #     'heater11TempIn2', 'heater11TempOut2', 'heater11PressIn2', 'heater11PressOut2', 'heater12Voltage1',
    #     'heater12Current1',
    #     'heater12Power1', 'heater12TempIn1', 'heater12TempOut1', 'heater12PressIn1', 'heater12PressOut1',
    #     'heater12Voltage2',
    #     'heater12Current2', 'heater12Power2', 'heater12TempIn2', 'heater12TempOut2', 'heater12PressIn2',
    #     'heater12PressOut2',
    #     'heater13Voltage1', 'heater13Current1', 'heater13Power1', 'heater13TempIn1', 'heater13PressIn1',
    #     'heater13PressOut1',
    #     'heater13Voltage2', 'heater13Current2', 'heater13Power2', 'heater13TempIn2', 'heater13TempOut2',
    #     'heater13PressIn2',
    #     'heater13PressOut2', 'heater14Voltage1', 'heater14Current1', 'heater14Power1', 'heater14TempIn1',
    #     'heater14TempOut1',
    #     'heater14PressIn1', 'heater14PressOut1', 'heater14Voltage2', 'heater14Current2', 'heater14Power2',
    #     'heater14TempIn2',
    #     'heater14TempOut2', 'heater14PressIn2', 'heater14PressOut2', 'heater15Voltage1', 'heater15Current1',
    #     'heater15Power1',
    #     'heater15TempIn1', 'heater15TempOut1', 'heater15PressIn1', 'heater15PressOut1', 'heater15Voltage2',
    #     'heater15Current2',
    #     'heater15Power2', 'heater15TempIn2', 'heater15TempOut2', 'heater15PressIn2', 'heater15PressOut2',
    #     'heater16Voltage1',
    #     'heater16Current1', 'heater16Power1', 'heater16TempIn1', 'heater16TempOut1', 'heater16PressIn1',
    #     'heater16PressOut1',
    #     'heater16Voltage2', 'heater16Current2', 'heater16Power2', 'heater16TempIn2', 'heater16TempOut2',
    #     'heater16PressIn2',
    #     'heater16PressOut2', 'heater17Voltage1', 'heater17Current1', 'heater17Power1', 'heater17TempIn1',
    #     'heater17TempOut1',
    #     'heater17PressIn1', 'heater17PressOut1', 'heater17Voltage2', 'heater17Current2', 'heater17Power2',
    #     'heater17TempIn2',
    #     'heater17TempOut2', 'heater17PressIn2', 'heater17PressOut2', 'heater18Voltage1', 'heater18Current1',
    #     'heater18Power1',
    #     'heater18TempIn1', 'heater18TempOut1', 'heater18PressIn1', 'heater18PressOut1', 'heater18Voltage2',
    #     'heater18Current2',
    #     'heater18Power2', 'heater18TempIn2', 'heater18TempOut2', 'heater18PressIn2', 'heater18PressOut2',
    #     'heater19Voltage1',
    #     'heater19Current1', 'heater19Power1', 'heater19TempIn1', 'heater19TempOut1', 'heater19PressIn1',
    #     'heater19PressOut1',
    #     'heater19Voltage2', 'heater19Current2', 'heater19Power2', 'heater19TempIn2', 'heater19TempOut2',
    #     'heater19PressIn2',
    #     'heater19PressOut2'
    # ]

    order_keys = ['pduPower', 'pduEnergy']

    sorted_dict = {key: input_dict[key] for key in order_keys if key in input_dict}

    for key, value in sorted_dict.items():
        # sorted_dict[key] = int(value)  # 转换成int类型值
        sorted_dict[key] = float(value)  # 转换成float类型值

    return sorted_dict








#
longrun_stack_neural = FIFO_Stack()
cdu_stack_neural = FIFO_Stack()
fsu_stack_neural = FIFO_Stack()

all_stack = FIFO_Stack()

bian = 0
count = 0

# 设置默认值，有问题再改
last_longrun_config_dict = {
    "dryValve1": 50,
    "dryValve2": 50,
    "dryValve3": 50,
    "dryValve4": 50,
    "dryValve5": 50,
    "pumpPump": 50,
    "pumpBypassValve": 50}
last_cdu_config_dict = {'cduValve1': 50}

# 状态参数
cdu_tso = []
cdu_tsi = []
cdu_tfi = []
cdu_tfo = []


len_state = 0

# 动作参数
dry_fan = []
cdu_valvue = []

# 室温
temp = []


def train_all_offline(all_file_list, epoch, batchSize, lr=0.1, dropout_rate = 0.2, need_all_key = None):
    from all_config import state_dict_path, is_not_restart_new_model, model
    '''

    :param all_file_list: 列表第一个元素为longrun文件，第二个为cdu，第三个为fsu
    :param epoch:
    :param batchSize:
    :param lr:
    :param dropout_rate:
    :param need_all_key:
    :return:
    '''

    ###############参数预定义部分##############

    if os.path.exists('memory.pkl') == False:
        file_path_longrun = all_file_list[0]
        df_longrun = pd.read_excel(file_path_longrun)
        myLogger.info(f'read longrun data completed!')
        file_path_cdu = all_file_list[1]
        df_cdu = pd.read_excel(file_path_cdu)
        myLogger.info(f'read cdu data completed!')
        file_path_fsu = all_file_list[2]
        df_fsu = pd.read_excel(file_path_fsu)
        # myLogger.info(f'read fsu data completed!')





    ######################超参数
        capacity = df_cdu.shape[0]
        memory = Replay_Buffer(capacity)

    ##############################

        ## 数据预处理相关队列
        deque_save_pre = deque([50, 50, 50, 50], maxlen=4)



        # ####################
        # 修改这里的同时注意修改后面的range
        ################################################组装经验池部分###########################################################

        line_read = df_cdu.shape[0]

        for i in range(1, line_read):
            row_longrun = df_longrun.iloc[i]
            json_str_longrun = row_longrun.to_json(date_format='iso', force_ascii=False)
            longrun_data = json.loads(json_str_longrun)
            # print("json_str_longrun:",longrun_data)
            row_cdu = df_cdu.iloc[i]
            json_str_cdu = row_cdu.to_json(date_format='iso', force_ascii=False)
            cdu_data = json.loads(json_str_cdu)

            row_fsu = df_fsu.iloc[i]
            json_str_fsu = row_fsu.to_json(date_format='iso', force_ascii=False)
            fsu_data = json.loads(json_str_fsu)

            # 这里对重要状态进行筛选,带有neural的是用于进行智能的状态值的输入（离线训练）
            #longrun_sorted_dict = process_longrundata(longrun_data)
            longrun_sorted_dict_neural = process_longrundata_neural(longrun_data)
            # myLogger.info(flen(longrun_sorted_dict): {len(longrun_sorted_dict)}")
            # myLogger.info(f'longrun_sorted_dict: {longrun_sorted_dict}')
            #cdu_sorted_dict = process_cdudata(cdu_data)
            cdu_sorted_dict_neural = process_cdudata_neural(cdu_data)

            #fsu_sorted_dict = process_fsudata(fsu_data)
            fsu_sorted_dict_neural = process_fsudata_neural(fsu_data)

            # all_sorted_dict = {**longrun_sorted_dict_neural, **cdu_sorted_dict_neural, **fsu_sorted_dict_neural}
            all_sorted_dict = {**longrun_sorted_dict_neural, **cdu_sorted_dict_neural, **fsu_sorted_dict_neural}

            all_pddata = pd.Series(all_sorted_dict)

    ###########################################################################################################

            new_all_sorted_dict = {}

            # 输入特征

            for key in need_all_key:
                if key == 'dryFan':

                    if all_sorted_dict[key] > 65530:
                        all_sorted_dict[key] = int(sum(deque_save_pre)/len(deque_save_pre))
                    deque_save_pre.append(all_sorted_dict[key])
                new_all_sorted_dict[key] = all_sorted_dict[key]


            #print(new_all_sorted_dict)
            new_all_sorted_dict.pop('cduTso')
            state_now = new_all_sorted_dict
            label_now = all_sorted_dict['cduTso']



            myLogger.info(f"'cduTso':{all_pddata['cduTso']}")
            myLogger.info(f"'temperature':{all_pddata['temperature']}")
            memory.push(state_now, label_now)
        with open('memory.pkl', 'wb') as f:
            print(f"已将当前的数据集缓存")
            pickle.dump(memory, f)

    else:
        with open('memory.pkl', 'rb') as f:
            memory = pickle.load(f)


    myLogger.info(f"经验池组装完毕")
    len_state = len(memory.buffer[0][0])
    line_read = len(memory.buffer)
#######################神经网络初始化##########################################

    device = torch.device(
        "cuda" if torch.cuda.is_available() else "cpu")
    if is_not_restart_new_model:
        model = Model(len_state).to(device)
    else:
        # 加载模型的状态字典
        state_dict = torch.load(state_dict_path, map_location=device)
        # 将状态字典加载到模型中
        model.load_state_dict(state_dict)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)

    cost = torch.nn.MSELoss(reduction='mean')
    optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=1e-3)# 优化器Adam可动态调整学习率
    #optimizer = optim.Adadelta(model.parameters(), lr=lr, rho=0.9, eps=1e-06, weight_decay=1e-4)
    scheduler = StepLR(optimizer, step_size=10, gamma=0.99)
    batchSize = batchSize
##################################################################
    episode = int((line_read / batchSize) * epoch)

    for episodes in range(episode):
        myLogger.info(f"当前训练的轮数为{episodes}")
        state_batch, label_batch = memory.sample(batchSize)
        #for i in list(range(len(state_batch))):
            # state_list = list(state_batch[i].values())
            # label_var = [label_batch[i]]
            #
            # # 将状态列表转换为tensor类型
            # xx = torch.tensor(state_list, dtype=torch.float).to(device)
            # yy = torch.tensor(label_var, dtype=torch.float).to(device)
            #
            #
            # # 通过神经网络来对状态进行预测
            # output_model = model(xx)
            # loss_list.append(cost(output_model, yy))
        # 先转换为列表类型
        state_batch_list = [list(x.values()) for x in state_batch]
        label_batch_list = [[x] for x in label_batch]

        #转换为tensor类型
        xx = torch.tensor(state_batch_list, dtype=torch.float).to(device)
        yy = torch.tensor(label_batch_list, dtype=torch.float).to(device)


        loss = cost(model(xx), yy)
        myLogger.info(f"train loss {loss.item()}")
        # 清零梯度
        optimizer.zero_grad()

        # 反向传播
        loss.backward()

        # 更新模型参数
        optimizer.step()

        # 更新学习率
        scheduler.step()

        current_lr = scheduler.get_last_lr()[0]
        myLogger.info(f"当前的学习率为{current_lr:.6f}")

    return model



# if __name__ == '__main__':
#     train_all_offline()